<?php

namespace App\Kuafu\Common\Jobs;

use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\Customer\Enum\PlatformCodeEnum;
use App\Kuafu\Customer\Model\CustomerModel;
use App\Kuafu\Customer\Model\CustomerPlatformModel;
use App\Kuafu\CustomerCoupon\Model\CustomerCouponModel;
use App\Kuafu\Shop\Enum\CodeEnum;
use App\Kuafu\Shop\Model\Shop;
use App\Kuafu\User\Model\User;
use BatchConsumer;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Validator;
use SensorsAnalytics;

class SensorsDataJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    /**
     * 异常标题
     */
    const EXCEPTION_TITLE = '【 消费队列 】【 神策埋点 】';

    /**
     * 队列名称
     *
     * @var string
     */
    public static string $QUEUE_NAME = '{RMS-SENSORS-DATA-QUEUE}';

    const TYPE_SUBMIT_ORDER             = 'SubmitOrder'; //提交订单
    const TYPE_SUBMIT_ORDER_MENU_DETAIL = 'SubmitOrder_MenuDetial'; //提交订单-菜品详情
    const TYPE_PAY_ORDER                = 'PayOrder'; // 支付订单
    const TYPE_PAY_ORDER_MENU_DETAIL    = 'PayOrder_MenuDetial'; //支付订单-菜品详情
    const TYPE_PAY_SUCCESS              = 'PaySuccess'; //支付成功
    const TYPE_PAY_SUCCESS_MENU_DETAIL  = 'PayResult_MenuDetial'; //支付成功-菜品详情
    const TYPE_CANCEL_ORDER             = 'CancelOrder'; //取消订单
    const TYPE_CANCEL_ORDER_MENU_DETAIL = 'CancelOrder_MenuDetial'; //取消订单-菜品详情
    const TYPE_RECEIVE_COUPON           = 'CollectCoupon'; //领取优惠券
    const TYPE_USE_COUPON               = 'UseCoupon'; //使用优惠券
    const TYPE_USER_BIND                = 'UserBind';//用户绑定
    const TYPE_BUY_COUPON_PACKAGE       = 'BuyCouponBag';//购买券包

    public static array $rule = [
        self::TYPE_BUY_COUPON_PACKAGE       => [
            'collect_scene'     => 'required',//业务场景
            'couponBag_id'      => 'required',//券包id
            'couponBag__name'   => 'required', //券包收音也是文案
            'couponBag_content' => 'required',//券包名称
            'coupon_quantity'   => 'required',//券包数量
            'couponBag__amount' => 'required'//券包售价
        ],
        self::TYPE_USER_BIND                => [
            'uid'    => 'required|int|min:1',
            'openid' => 'required'
        ],
        self::TYPE_SUBMIT_ORDER             => [
            //提交订单
            'order_no'        => 'required',//订单编号 |STRING|
            'order_amount'    => 'required',//订单金额 |NUMBER| 菜品总金额：统计所有菜品⾦额=
            'discount_amount' => 'required',//优惠折扣 |STRING|
            'pay_amount'      => 'required',//优惠后金额 |NUMBER| 优惠后的菜品总金额
        ],
        self::TYPE_SUBMIT_ORDER_MENU_DETAIL => [
            //提交订单-菜品详情
            'order_no'           => 'required',//订单编号 |STRING|
            'menu_type'          => 'required',//菜品分类 |STRING| 必吃，素串系列，卤油炸串，套餐类等
            'menu_name'          => 'required',//菜品名称 |STRING| 如果是套餐组合，传套餐名称
            'menu_originalPrice' => 'required',//菜品原价 |STRING|
            'menu_quantity'      => 'required',//菜品数量 |STRING|
            'menu_amount'        => 'required',//菜品金额 |NUMBER| 菜品⾦额默认为菜品原价*菜品份额
            'discount_amount'    => 'required',//优惠折扣 |STRING|
            'pay_amount'         => 'required',//优惠后金额 |NUMBER| 优惠后的菜品总金额
        ],
        self::TYPE_PAY_ORDER                => [
            //支付订单
            'order_time'      => 'required|date_format:Y-m-d H:i:s',//订单时间 |DATETIME|
            'order_no'        => 'required',//订单编号 |STRING|
            'order_amount'    => 'required',//订单金额 |NUMBER| 菜品总金额：统计所有菜品⾦额=
            'discount_amount' => 'required',//优惠折扣 |STRING|
            'pay_amount'      => 'required',//优惠后金额 |NUMBER| 优惠后的菜品总金额
            'if_consumCoupon' => 'required',//是否使用优惠券 |BOOL|
            'coupon_quantity' => 'required',//优惠券数量 |number|
            'comment'         => '',//备注 |STRING| 口味，偏好备注内容
        ],
        self::TYPE_PAY_ORDER_MENU_DETAIL    => [
            //支付订单_菜品详情
            'order_time'         => 'required|date_format:Y-m-d H:i:s',//订单时间 |DATETIME|
            'order_no'           => 'required',//订单编号 |STRING|
            'menu_type'          => 'required',//菜品分类 |STRING| 必吃，素串系列，卤油炸串，套餐类等
            'menu_name'          => 'required',//菜品名称 |STRING| 如果是套餐组合，传套餐名称
            'menu_originalPrice' => 'required',//菜品原价 |STRING|
            'menu_quantity'      => 'required',//菜品数量 |STRING|
            'menu_amount'        => 'required',//菜品��额 |NUMBER| 菜品⾦额默认为菜品原价*菜品份额
            'discount_amount'    => 'required',//优惠折扣 |STRING|
            'pay_amount'         => 'required',//优惠后金额 |NUMBER| 优惠后的菜品总金额
            'comment'            => '',//备注 |STRING| 口味，偏好备注内容
        ],
        self::TYPE_PAY_SUCCESS              => [
            //支付成功
            'pay_type'        => 'required',//支付方式 |STRING|
            'order_time'      => 'required',//订单时间 |DATETIME|
            'order_no'        => 'required',//订单编号 |STRING|
            'order_amount'    => 'required',//订单金额 |NUMBER|
            'discount_amount' => 'required',//优惠折扣 |STRING|
            'pay_amount'      => 'required',//优惠后金额 |NUMBER|
            'if_consumCoupon' => 'required',//是否使用优惠券 |BOOL|
            'coupon_quantity' => 'required',//优惠券数量 |number|
            'menu_number'     => 'required',//取餐号 |STRING|
            'comment'         => '',//备注 |STRING|
        ],
        self::TYPE_PAY_SUCCESS_MENU_DETAIL  => [
            //支付成功_菜品详情
            'order_time'         => 'required',//订单时间 |DATETIME|
            'order_no'           => 'required',//订单编号 |STRING|
            'menu_type'          => 'required',//菜品分类 |STRING|
            'menu_name'          => 'required',//菜品名称 |STRING|
            'menu_originalPrice' => 'required',//菜品原价 |STRING|
            'menu_quantity'      => 'required',//菜品数量 |STRING|
            'menu_amount'        => 'required',//菜品金额 |NUMBER|
            'discount_amount'    => 'required',//优惠折扣 |STRING|
            'pay_amount'         => 'required',//优惠后金额 |NUMBER|
            'menu_number'        => 'required',//取餐号 |STRING|
            'comment'            => '',//备注 |STRING|
        ],
        self::TYPE_CANCEL_ORDER             => [
            //取消订单
            'order_no'        => 'required',//订单编号 STRING
            'order_time'      => 'required',//订单时间 DATETIME 提交订单的时间
            'order_amount'    => 'required',//订单金额 NUMBER
            'discount_amount' => 'required',//优惠折扣 STRING
            'pay_amount'      => 'required',//优惠后金额 NUMBER
            'cancel_type'     => 'required',//取消类型 STRING 用户主动取消，订单支付超时
        ],
        self::TYPE_CANCEL_ORDER_MENU_DETAIL => [
            //取消订单_菜品详情
            'order_time'         => 'required',//订单时间 DATETIME
            'order_no'           => 'required',//订单编号 STRING
            'menu_type'          => 'required',//菜品分类 STRING
            'menu_name'          => 'required',//菜品名称 STRING
            'menu_originalPrice' => 'required',//菜品原价 STRING
            'menu_quantity'      => 'required',//菜品数量 STRING
            'menu_amount'        => 'required',//菜品金额 NUMBER
            'discount_amount'    => 'required',//优惠折扣 STRING
            'pay_amount'         => 'required',//优惠后金额 NUMBER
            'cancel_type'        => 'required',//取消类型 STRING 用户主动取消，订单支付超时
        ],
        self::TYPE_RECEIVE_COUPON           => [
            //领取优惠券
            'access_way'        => 'required',//取值事例：领取，购买券包
            'collect_scene'     => 'required',//领取场景 STRING 弹窗
            'user_coupon_id'    => 'required', //用户优惠券id string
            'coupon_id'         => 'required',//优惠券id STRING
            'coupon_type'       => 'required',//优惠券类型 STRING 折扣券，满减券
            'coupon_name'       => 'required',//优惠券名称 STRING 新人优惠券
            'coupon_content'    => 'required',//优惠券内容 STRING 满xx减xx
            'coupon_amount'     => 'required',//优惠券金额 NUMBER 券面值
            'coupon_discount'   => 'required',//优惠券折扣 STRING 6.8折
            'coupon_period'     => 'required',//优惠券有效期 STRING
            'coupon_startDate'  => 'required',//优惠券开始日期 DATETIME
            'coupon_endDate'    => 'required',//优惠券结束日期 DATETIME
            'couponBag_id'      => '',//如果是购买券包获取的，上报所属券包信息
            'couponBag__name'   => '',//如果是购买券包获取的，上报所属券包信息
            'couponBag_content' => '',//券包名称
        ],
        self::TYPE_USE_COUPON               => [
            //核销优惠券
            'order_time'       => 'required',//订单时间 DATETIME
            'order_no'         => 'required', //订单编号 string
            'user_coupon_id'   => 'required', //用户优惠券id string
            'coupon_id'        => 'required',//优惠券id STRING
            'coupon_type'      => 'required',//优惠券类型 STRING 折扣券，满减券
            'coupon_name'      => 'required',//优惠券名称 STRING 新人优惠券
            'coupon_content'   => 'required',//优惠券内容 STRING 满xx减xx
            'coupon_amount'    => 'required',//优惠券金额 NUMBER 6
            'coupon_discount'  => 'required',//优惠券折扣 STRING 6.8折
            'coupon_period'    => 'required',//优惠券有效期 STRING
            'coupon_startDate' => 'required',//优惠券开始日期 DATETIME
            'coupon_endDate'   => 'required',//优惠券结束日期 DATETIME
        ],
    ];

    public int    $shopId;
    public string $type;
    public array  $extra;
    public int    $uid;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($shopId, $uid, $type, $extra)
    {
        $this->shopId = $shopId;
        $this->uid    = $uid;
        $this->type   = $type;
        $this->extra  = $extra;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        try {
            $serverUrl = Config::get("sensors.serverUrl", "");
            if (empty($serverUrl)) {
                throw new \Exception('神策埋点提交地址获取失败');
            }

            if (!isset(self::$rule[$this->type])) {
                throw new \Exception('无法识别的埋点标识');
            }

            $validateResult = Validator::make($this->extra, self::$rule[$this->type]);
            if ($validateResult->fails()) {
                throw new \Exception('参数校验未通过' . $validateResult->errors()->first());
            }

            //获取门店信息
            $shopDetail = Shop::query()->where('id', $this->shopId)->first();
            //获取平台信息
            $userPlatformInfo = CustomerPlatformModel::query()
                                                     ->where('userId', $this->uid)
                                                     ->where('platformId', PlatformCodeEnum::PLATFORM_APPLET_WECHAT_APPLET)
                                                     ->first();
            //获取券数量
            $customerCouponCount = (int)CustomerCouponModel::query()
                                                           ->where('userId', $this->uid)
                                                           ->where('status',
                                                               \App\Kuafu\CustomerCoupon\Enum\CodeEnum::COUPON_STATUS_NO_USED)
                                                           ->count();

            $consumer = new BatchConsumer($serverUrl);
            $sa       = new SensorsAnalytics($consumer);
            # 设置事件公共属性
            $sa->register_super_properties([
                'store_id'   => $shopDetail ? CommonService::zeroFill($shopDetail->id) : '',
                'store_name' => $shopDetail ? $shopDetail->name : '',
                'store_type' => $shopDetail ? CodeEnum::TYPE_MAP[$shopDetail->type] : ''
            ]);
            # 设置用户属性
            $sa->profile_set($this->uid, true, [
                    'register_firstTime' => $userPlatformInfo ? date('Y-m-d H:i:s',
                        $userPlatformInfo->createdAt->timestamp) : '',
                    'coupon_quantity'    => (int)$customerCouponCount
                ]
            );

            if ($this->type == self::TYPE_USER_BIND) {
                //匿名绑定
                $sa->track_signup($this->uid, $this->extra['openid']);
            } else {
                //事件触发
                $sa->track($this->uid, true, $this->type, $this->extra);
            }

            $sa->flush();
        } catch (\Exception $e) {
            CommonService::fsLogException(self::EXCEPTION_TITLE, $e,
                Collect(get_object_vars($this))->only(['shopId', 'uid', 'type', 'extra', 'queue'])->toArray(), true);
        }
    }
}
